#include "includes.h"

#define PROTOCOL_PORT 8000
int sockfd;




int init_communication_protocol()
{
	struct sockaddr_in servaddr;
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(PROTOCOL_PORT);
	sockfd = Socket(AF_INET, SOCK_DGRAM, 0);
	Bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr));
	return 0;
}

static int send_packet(const char *packet_addr, int packet_len, struct sockaddr *pstAddr)
{
	int i;
	printf("PACKET SEND<<");
	for(i=0; i<packet_len; i++)
			printf("%02x ", packet_addr[i]);
	printf(">>END\n");
	Sendto(sockfd, (const void *)packet_addr, packet_len, 0, (struct sockaddr *)pstAddr, sizeof(struct sockaddr));
	return 0;
}

int send_ack_packet(char err_no, PS_PACKET_DATA pstRequest, struct sockaddr *pstAddr)
{
	char *buff;
	PS_PACKET_DATA pstPacket;
	int packet_len;

	packet_len = sizeof(S_PACKET_DATA)+sizeof(S_PACKET_ERR_DATA);
	buff = Malloc(packet_len);
	bzero(buff, packet_len);
	pstPacket = (PS_PACKET_DATA)buff;
	pstPacket->type = TYPE_ACK;
	pstPacket->content = pstRequest->content;
	pstPacket->sn = pstRequest->sn;
	pstPacket->data_len = sizeof(S_PACKET_ERR_DATA);
	*pstPacket->data = err_no;
	send_packet(buff, packet_len, pstAddr);
	free(buff);
	return 0;
}

int send_ack_data_packet(char err_no, PS_PACKET_DATA pstRequest, struct sockaddr *pstAddr, char *data, int data_len)
{
	char *buff;
	PS_PACKET_DATA pstPacket;
	PS_PACKET_ERR_DATA pstPacket_err;
	int packet_len;

	if (data == NULL)
		data_len = 0;
	packet_len = sizeof(S_PACKET_DATA)+sizeof(S_PACKET_ERR_DATA)+data_len;
	buff = Malloc(packet_len);
	bzero(buff, packet_len);
	pstPacket = (PS_PACKET_DATA)buff;
	pstPacket->type = TYPE_ACK_DATA;
	pstPacket->content = pstRequest->content;
	pstPacket->sn = pstRequest->sn;
	pstPacket->data_len = sizeof(S_PACKET_ERR_DATA)+data_len;
	pstPacket_err = (PS_PACKET_ERR_DATA)(buff+sizeof(S_PACKET_DATA));
	pstPacket_err->err_no = err_no;
	if (data)
		memcpy(pstPacket_err->err_data, data, data_len);
	send_packet(buff, packet_len, pstAddr);
	free(buff);
	return 0;
}





void *communication(void *arg)
{
	char recv_buff[1024];
	int len;
	int addr_len;
	struct sockaddr addr;
	PS_PACKET_DATA pstPacket;	
	unsigned char packet_type;
	int i;
	
	while(1)
	{
		addr_len = sizeof(struct sockaddr);
		len = Recvfrom(sockfd, (void *)recv_buff, sizeof(recv_buff), 0, &addr, (socklen_t *)&addr_len);
		pstPacket = (PS_PACKET_DATA)recv_buff;
		printf("PACKET RECV<<");
		for(i=0; i<len; i++)
			printf("%02x ", recv_buff[i]);
		printf(">>END\n");
		packet_type = pstPacket->type;
		switch(packet_type)
		{
			case TYPE_REQUEST:
				if (get_sys_stat() == STAT_SYS_FREE) //new task
				{
					updata_sys_stat(pstPacket, &addr);
					send_ack_packet(ERR_CODE_OK, pstPacket, &addr);
					task_buff_write(recv_buff, len);
				}
				else
				{
					send_ack_packet(ERR_CODE_BUSY, pstPacket, &addr);
				}
				break;
			case TYPE_REQUEST_DATA:
				if (get_cur_sn() == pstPacket->sn)
				{
					if (get_sys_stat() == STAT_SYS_MIDDLE)
					{
						task_buff_write(recv_buff, len);
					}
					else if (get_sys_stat() == STAT_SYS_BUSY)
					{
						send_ack_data_packet(ERR_CODE_BUSY, pstPacket, &addr, NULL, 0);
					}
					else
					{
						send_ack_data_packet(ERR_CODE_TIME, pstPacket, &addr, NULL, 0);
					}
				}
				break;
			case TYPE_ACK_ACK:
			default:
				if (get_cur_sn() == pstPacket->sn)
				{
					if (get_sys_stat() == STAT_SYS_MIDDLE)
					{
						task_buff_write(recv_buff, len);
					}
				}
				break;

		}
	}
}


